package org.rcy.framework.data.config.mybatis.plugins;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.ResultFlag;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.rcy.framework.data.dao.IdEntityHandler;
import org.rcy.framework.data.util.FieldReflectUtil;
import org.rcy.framework.data.util.PersistentUtil;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.entity.EntityTable;
import tk.mybatis.mapper.mapperhelper.EntityHelper;

public class ResultMapSwapper {
    private final Log log = LogFactory.getLog(ResultMapSwapper.class);
    private Configuration configuration;
    private ConcurrentHashMap<String, ResultMap> resultMaps = new ConcurrentHashMap();

    public ResultMapSwapper(Configuration configuration) {
        this.configuration = configuration;
    }

    public ResultMap reloadResultMap(String resource, String id, Class<?> type) {
        if (!this.resultMaps.containsKey(id)) {
            this.resultMaps.put(id, this.resolveResultMap(resource, id, type));
        }

        return (ResultMap)this.resultMaps.get(id);
    }

    public void registerResultMap(ResultMap resultMap) {
        this.configuration.addResultMap(resultMap);
    }

    public ResultMap resolveResultMap(String resource, String id, Class<?> type) {
        List<ResultMapping> resultMappings = this.resolveResultMappings(resource, id, type);
        return (new ResultMap.Builder(this.configuration, id, type, resultMappings)).build();
    }

    private List<ResultMapping> resolveResultMappings(String resource, String id, Class<?> type) {
        List<ResultMapping> resultMappings = new ArrayList();
        MapperBuilderAssistant assistant = new MapperBuilderAssistant(this.configuration, resource);
        List<Field> fields = PersistentUtil.getPersistentFields(type);
        Iterator var7 = fields.iterator();

        while(var7.hasNext()) {
            Field field = (Field)var7.next();
            String property = field.getName();
            String column = PersistentUtil.getColumnName(field, this.configuration.isMapUnderscoreToCamelCase());
            Class<?> javaType = field.getType();
            JdbcType jdbcType = null;
            String nestedSelect = null;
            String nestedResultMap = null;
            Class actualType;
            if (PersistentUtil.isAssociationField(field)) {
                column = PersistentUtil.getMappedName(field);
                if (field.isAnnotationPresent(OneToOne.class)) {
                    nestedResultMap = id + "_association[" + javaType.getSimpleName() + "]";
                    this.registerResultMap(this.resolveResultMap(resource, nestedResultMap, javaType));
                }

                if (field.isAnnotationPresent(OneToMany.class)) {
                    actualType = FieldReflectUtil.getGenericType(field);
                    nestedResultMap = id + "collection[" + actualType.getSimpleName() + "]";
                    this.registerResultMap(this.resolveResultMap(resource, nestedResultMap, actualType));
                }
            }

            actualType = null;
            String columnPrefix = null;
            String resultSet = null;
            String foreignColumn = null;
            List<ResultFlag> flags = new ArrayList();
            if (field.isAnnotationPresent(Id.class)) {
                flags.add(ResultFlag.ID);
            }

            boolean lazy = false;
            Class<? extends TypeHandler<?>> typeHandler = this.getTypeHandler(type, field);
            ResultMapping resultMapping = assistant.buildResultMapping(type, property, column, javaType, (JdbcType)jdbcType, (String)nestedSelect, nestedResultMap, actualType.getSimpleName(), (String)columnPrefix, typeHandler, flags, (String)resultSet, (String)foreignColumn, lazy);
            resultMappings.add(resultMapping);
        }

        return resultMappings;
    }

    private Class<? extends TypeHandler<?>> getTypeHandler(Class<?> type, Field field) {
        Class<? extends TypeHandler<?>> typeHandler = null;

        try {
            if (IdEntityHandler.getIdEntityClass() != null && IdEntityHandler.getIdEntityClass().isAssignableFrom(field.getType())) {
                EntityTable entityTable = EntityHelper.getEntityTable(type);
                Map<String, EntityColumn> propertyMap = entityTable.getPropertyMap();
                EntityColumn entityColumn = (EntityColumn)propertyMap.get(field.getName());
                typeHandler = entityColumn.getTypeHandler();
            }

            return typeHandler;
        } catch (Exception var7) {
            this.log.warn(type.getName() + " field " + field.getName() + " getTypeHandler error " + var7.getMessage());
            return null;
        }
    }
}
